package com.znyj.cloud.thrift;

import com.znyj.cloud.chain.util.CheckUtil;
import com.znyj.cloud.chain.util.SpringContextHelper;
import com.znyj.cloud.device.constant.SysConstant;
import com.znyj.cloud.device.entity.TaskEntity;
import com.znyj.cloud.device.executor.ReportExecutorService;
import com.znyj.cloud.device.executor.TaskExecutorService;
import com.znyj.cloud.device.pack.AtomicValues;
import com.znyj.cloud.device.pack.TaskSendPackage;
import com.znyj.cloud.device.service.ReportService;
import com.znyj.cloud.device.service.TaskService;
import com.znyj.cloud.device.task.ControlTaskMapping;
import com.znyj.cloud.device.task.OnlineDeviceInfoMapping;
import com.znyj.cloud.device.task.model.ControlTaskModel;
import com.znyj.cloud.thrift.lower.*;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;

import java.sql.Timestamp;
import java.util.Date;

/**
 * Created by gaoliwei02 on 17/8/9.
 */

public class InnerThriftServiceImpl implements InnerThriftService.Iface {
    private static final Logger logger = Logger.getLogger(InnerThriftServiceImpl.class);

    @Override
    public ResponseTaskMsg sendTask2backEnd(RequestTaskMsg msg) throws TException {
        Date begin = new Date();
        ResponseTaskMsg responseTaskMsg;
        String userId = msg.getUserId();
        String deviceId = msg.getDeviceId();
        String controlMsg = msg.getControlMsg();
        long durationSec = msg.getDurationSec();
        String userLocation = msg.getUserLocation();
        Timestamp createTime;
        if (msg.getCreateTime() == 0) createTime = new Timestamp(SysConstant.TIME_2000);
        else createTime = new Timestamp(msg.getCreateTime());

        //消息格式有错误
        if (!CheckUtil.IsValid(userId, deviceId, controlMsg, durationSec)) {
            logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_MSG_NOT_VALID, msg.toString(), Long.parseLong(deviceId)));
            responseTaskMsg = new ResponseTaskMsg(userId, deviceId, -1, SysConstant.API_ERROR_CODE.THRIFT_MSG_INVALID);
            return responseTaskMsg;
        }

        //检查设备是否在线
        if (!OnlineDeviceInfoMapping.contain(deviceId)) {
            logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_DEV_NOT_ONLINE, msg.toString(), Long.parseLong(deviceId)));
            responseTaskMsg = new ResponseTaskMsg(userId, deviceId, -1, SysConstant.API_ERROR_CODE.THRIFT_DEV_OFFLINE);
            return responseTaskMsg;
        }

        //检查open是否已经open，close是否已经空闲
        switch (controlMsg) {
            case "cdbaopen": {
                ReportService reportService = SpringContextHelper.getBean(ReportService.class);
                long orderId = reportService.getChannalAOrderId(deviceId);
                if (orderId != 0) {
                    responseTaskMsg = new ResponseTaskMsg(userId, deviceId, orderId, SysConstant.API_ERROR_CODE.THRIFT_OPEN_ALREADY);
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_OPEN_ALREADY, "cdbaopen", orderId));
                    return responseTaskMsg;
                }
            }
            break;

            case "cdbbopen": {
                ReportService reportService = SpringContextHelper.getBean(ReportService.class);
                long orderId = reportService.getChannalBOrderId(deviceId);
                if (orderId != 0) {
                    responseTaskMsg = new ResponseTaskMsg(userId, deviceId, orderId, SysConstant.API_ERROR_CODE.THRIFT_OPEN_ALREADY);
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_OPEN_ALREADY, "cdbbopen", orderId));
                    return responseTaskMsg;
                }
            }
            break;

            case "cdbaclose": {
                ReportService reportService = SpringContextHelper.getBean(ReportService.class);
                long orderId = reportService.getChannalAOrderId(deviceId);
                if (orderId == 0) {
                    responseTaskMsg = new ResponseTaskMsg(userId, deviceId, 0, SysConstant.API_ERROR_CODE.THRIFT_CLOSE_ALREADY);
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_CLOSE_ALREADY, "cdbaclose", orderId));
                    return responseTaskMsg;
                }
            }
            break;

            case "cdbbclose": {
                ReportService reportService = SpringContextHelper.getBean(ReportService.class);
                long orderId = reportService.getChannalBOrderId(deviceId);
                if (orderId == 0) {
                    responseTaskMsg = new ResponseTaskMsg(userId, deviceId, 0, SysConstant.API_ERROR_CODE.THRIFT_CLOSE_ALREADY);
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_CLOSE_ALREADY, "cdbbclose", orderId));
                    return responseTaskMsg;
                }
            }
            break;


            case "cdbopen": {
                ReportService reportService = SpringContextHelper.getBean(ReportService.class);
                long orderId = reportService.getChannalAOrderId(deviceId);
                if (orderId != 0) {
                    responseTaskMsg = new ResponseTaskMsg(userId, deviceId, orderId, SysConstant.API_ERROR_CODE.THRIFT_OPEN_ALREADY);
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_OPEN_ALREADY, "cdbopen", orderId));
                    return responseTaskMsg;
                }
            }
            break;

            case "cdbclose": {
                ReportService reportService = SpringContextHelper.getBean(ReportService.class);
                long orderId = reportService.getChannalAOrderId(deviceId);
                if (orderId == 0) {
                    responseTaskMsg = new ResponseTaskMsg(userId, deviceId, 0, SysConstant.API_ERROR_CODE.THRIFT_CLOSE_ALREADY);
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.THRIFT_CLOSE_ALREADY, "cdbclose", orderId));
                    return responseTaskMsg;
                }
            }
            break;

            default: {

            }
            break;
        }

        //同时打开AB，或者同时关闭AB
        //logger.error("thrift api {}" + userId + " " + deviceId + " " + controlMsg + " " + durationSec);

        //反射获取bean
        TaskExecutorService taskExecutorService = SpringContextHelper.getBean(TaskExecutorService.class);
        ControlTaskMapping controlTaskMapping = SpringContextHelper.getBean(ControlTaskMapping.class);

        if (controlMsg.equals("cdbopen")) {
            StringBuilder controlA = new StringBuilder(controlMsg);
            controlA.insert(3, "a");
            StringBuilder controlB = new StringBuilder(controlMsg);
            controlB.insert(3, "b");

            long orderIdA = AtomicValues.incOrderId();
            long orderIdB = AtomicValues.incOrderId();

            TaskSendPackage taskSendPackageA = new TaskSendPackage(createTime, userId, deviceId, orderIdA, durationSec, 0, controlA.toString(), userLocation, "open bind B:" + String.valueOf(orderIdB));
            logger.info(CheckUtil.dataReport("@openall_a@", taskSendPackageA.reportJson()));


            taskExecutorService.executeInsertTask(taskSendPackageA);
            ControlTaskModel controlTaskModelA = new ControlTaskModel(taskSendPackageA, 0);
            controlTaskMapping.add(deviceId, controlTaskModelA);

            TaskSendPackage taskSendPackageB = new TaskSendPackage(createTime, userId, deviceId, orderIdB, durationSec, 0, controlB.toString(), userLocation, "open bind A:" + String.valueOf(orderIdA));
            logger.info(CheckUtil.dataReport("@openall_b@", taskSendPackageB.reportJson()));

            taskExecutorService.executeInsertTask(taskSendPackageB);
            ControlTaskModel controlTaskModelB = new ControlTaskModel(taskSendPackageB, 2);
            controlTaskMapping.add(deviceId, controlTaskModelB);

            responseTaskMsg = new ResponseTaskMsg(userId, deviceId, orderIdA, SysConstant.API_ERROR_CODE.THRIFT_SEND_TASK_OK);//sendTaskOk
        } else if (controlMsg.equals("cdbclose")) {

            StringBuilder controlA = new StringBuilder(controlMsg);
            controlA.insert(3, "a");
            StringBuilder controlB = new StringBuilder(controlMsg);
            controlB.insert(3, "b");

            long orderIdA = AtomicValues.incOrderId();
            long orderIdB = AtomicValues.incOrderId();


            TaskSendPackage taskSendPackageA = new TaskSendPackage(createTime, userId, deviceId, orderIdA, durationSec, 0, controlA.toString(), userLocation, "close all");
            logger.info(CheckUtil.dataReport("@closeall_a@", taskSendPackageA.reportJson()));
            taskExecutorService.executeInsertTask(taskSendPackageA);
            ControlTaskModel controlTaskModelA = new ControlTaskModel(taskSendPackageA, 0);
            controlTaskMapping.add(deviceId, controlTaskModelA);

            TaskSendPackage taskSendPackageB = new TaskSendPackage(createTime, userId, deviceId, orderIdB, durationSec, 0, controlB.toString(), userLocation, "close all");
            logger.info(CheckUtil.dataReport("@closeall_b@", taskSendPackageB.reportJson()));
            taskExecutorService.executeInsertTask(taskSendPackageB);
            ControlTaskModel controlTaskModelB = new ControlTaskModel(taskSendPackageB, 2);
            controlTaskMapping.add(deviceId, controlTaskModelB);

            responseTaskMsg = new ResponseTaskMsg(userId, deviceId, orderIdA, SysConstant.API_ERROR_CODE.THRIFT_SEND_TASK_OK);//sendTaskOk
        } else {
            //如果在线 插入数据库 open的话直接开启存数据库 close可能是定时服务发过来的 也可能是实时关闭过来的
            long orderId = AtomicValues.incOrderId();
            TaskSendPackage taskSendPackage = new TaskSendPackage(createTime, userId, deviceId, orderId, durationSec, 0, controlMsg, userLocation, "single");
            logger.info(CheckUtil.dataReport("@control_task@", taskSendPackage.reportJson()));
            //插入数据库
            taskExecutorService.executeInsertTask(taskSendPackage);
            //插入发送任务队列
            ControlTaskModel controlTaskModel = new ControlTaskModel(taskSendPackage, 0);
            controlTaskMapping.add(deviceId, controlTaskModel);

            responseTaskMsg = new ResponseTaskMsg(userId, deviceId, orderId, SysConstant.API_ERROR_CODE.THRIFT_SEND_TASK_OK);//sendTaskOk
        }
        logger.info(CheckUtil.timeTakeReport(begin,deviceId));
        return responseTaskMsg;
    }

    @Override
    public ResponseUpdateMsg sendUpdate2backEnd(RequestUpdateMsg msg) throws TException {
        ResponseUpdateMsg responseUpdateMsg;
        String userId = msg.getUserId();
        String deviceId = msg.getDeviceId();
        String upMsg = msg.getUpMsg();

        if (!CheckUtil.IsValid(userId, deviceId, upMsg)) {
            responseUpdateMsg = new ResponseUpdateMsg(userId, deviceId, -1, SysConstant.API_ERROR_CODE.THRIFT_MSG_INVALID);
            return responseUpdateMsg;
        }

        //检查deviceId是否在线
        if (!OnlineDeviceInfoMapping.contain(deviceId)) {
            logger.error("up deviceId not online!" + msg);
            responseUpdateMsg = new ResponseUpdateMsg(userId, deviceId, -1, SysConstant.API_ERROR_CODE.THRIFT_DEV_OFFLINE);
            return responseUpdateMsg;
        } else {
            //如果在线 插入数据库
            long orderId = AtomicValues.incOrderId();
            Timestamp createTime = new Timestamp(System.currentTimeMillis());
            TaskSendPackage taskSendPackage = new TaskSendPackage(createTime, userId, deviceId, orderId, 0, 0, upMsg, "", "");
            logger.info("single update:" + taskSendPackage.reportJson());

            TaskExecutorService taskExecutorService = SpringContextHelper.getBean(TaskExecutorService.class);
            ControlTaskMapping controlTaskMapping = SpringContextHelper.getBean(ControlTaskMapping.class);
            taskExecutorService.executeInsertTask(taskSendPackage);
            ControlTaskModel controlTaskModel = new ControlTaskModel(taskSendPackage, 0);
            controlTaskMapping.add(deviceId, controlTaskModel);

            //更新ota时间
            ReportExecutorService reportExecutorService = SpringContextHelper.getBean(ReportExecutorService.class);
            reportExecutorService.executeUpdateOtaTime(deviceId);

            responseUpdateMsg = new ResponseUpdateMsg(userId, deviceId, orderId, SysConstant.API_ERROR_CODE.THRIFT_SEND_UP_OK);
            return responseUpdateMsg;
        }
    }

    @Override
    public ResponseTaskMsg resendTask2backEnd(long orderId, String deviceId, long createTime, String controlMsg) throws TException {
        ResponseTaskMsg responseTaskMsg;
        ControlTaskMapping controlTaskMapping = SpringContextHelper.getBean(ControlTaskMapping.class);

        TaskSendPackage taskSendPackage = new TaskSendPackage(new Timestamp(createTime), "resend", deviceId, orderId, 0, 0, controlMsg, "", "");
        logger.info(CheckUtil.dataReport("@resend@", taskSendPackage.reportJson()));
        ControlTaskModel controlTaskModel = new ControlTaskModel(taskSendPackage, 0);
        controlTaskMapping.add(deviceId, controlTaskModel);

        responseTaskMsg = new ResponseTaskMsg("resend", deviceId, orderId, SysConstant.API_ERROR_CODE.THRIFT_SEND_TASK_OK);//sendTaskOk
        return responseTaskMsg;
    }

    @Override
    public String getRealTimeDeviceInfo(String deviceId) throws TException {
        if (OnlineDeviceInfoMapping.contain(deviceId)) {
            return "online";
        } else {
            return "offline";
        }
    }

//    @Override
//    public InfoOfOrderId getOrderIdInfo(long orderId) throws TException {
//        logger.error("@@@@@@@@@@@@@@@@ begin");
//        TaskService taskService = SpringContextHelper.getBean(TaskService.class);
//        TaskEntity taskEntity = taskService.findByOrderId(orderId);
//        InfoOfOrderId infoOfOrderId = new InfoOfOrderId(
//                taskEntity.getUserId(),
//                taskEntity.getDeviceId(),
//                taskEntity.getOrderId(),
//                taskEntity.getCreateTime().getTime(),
//                taskEntity.getDurationSec(),
//                taskEntity.getSendStatus(),
//                taskEntity.getControlMsg(),
//                taskEntity.getUserLocation()
//                //cdbTaskEntity.getExecuteResult()
//        );
//        logger.error("@@@@@@@@@@@@@@@@ end");
//        return infoOfOrderId;
//    }
}
